package com.newangels.util;

import jade.core.Agent;
import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;
import jade.wrapper.ContainerController;
import jade.wrapper.StaleProxyException;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.sql.Blob;
import java.sql.SQLException;
import java.text.Collator;
import java.util.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
 * 基本工具类
 *
 * @author: TangLiang
 * @date: 2020/4/9 10:13
 * @since 1.5
 */
public class BaseUtil {
    private static Logger logger = Logger.getLogger(BaseUtil.class.getName());

    /**
     * 获得UUID
     *
     * @return
     */
    public static String getUuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 获得文件名称
     *
     * @param filePath 文件路径
     * @return
     */
    public static String getFileName(String filePath) {
        String filePaths[] = filePath.split("[\\\\|/]");
        return filePaths[filePaths.length - 1];
    }

    /**
     * 根据汉字的拼音顺序排序
     *
     * @param list List
     * @return 排序后的List
     */
    public static List<String> sortByPinyin(List<String> list) {
        class PinyinComparator implements Comparator<String>, Serializable {
            private static final long serialVersionUID = 1L;
            final Collator collator;

            public PinyinComparator() {
                collator = Collator.getInstance(Locale.CHINESE);
            }

            @Override
            public int compare(String o1, String o2) {
                return collator.compare(o1, o2);
            }
        }
        list.sort(new PinyinComparator());
        return list;
    }

    /**
     * 分页
     *
     * @param list  需要分页的list
     * @param page  当前页数
     * @param limit 每次展示页数
     * @return 分页后的list
     */
    public static <T> List<T> page(List<T> list, Integer page, Integer limit) {
        return page != null && limit != null && page > 0 && limit > 0 ?
                list.stream()
                        .skip(limit * (page - 1))
                        .limit(limit)
                        .collect(Collectors.toList())
                : list;
    }

    /**
     * file转换Byte数组
     *
     * @param file File文件
     * @return Byte数组
     */
    public static byte[] fileToBytes(File file) {
        InputStream in;
        try {
            in = new FileInputStream(file);
            int len = in.available();
            byte[] result = new byte[len];
            in.read(result);
            in.close();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 数据库Blob文件存到指定路径
     *
     * @param blob 数据库Blob文件
     * @param path Blob存放路径
     */
    public static void blobToFile(Blob blob, String path) {
        try {
            InputStream in = blob.getBinaryStream();
            OutputStream out = new FileOutputStream(path);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.close();
            in.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 把Blob类型转换为byte数组类型
     *
     * @param blob
     * @return
     */
    public static byte[] blobToBytes(Blob blob) {
        BufferedInputStream is = null;
        try {
            is = new BufferedInputStream(blob.getBinaryStream());
            byte[] bytes = new byte[(int) blob.length()];
            int len = bytes.length;
            int offset = 0;
            int read = 0;
            while (offset < len
                    && (read = is.read(bytes, offset, len - offset)) >= 0) {
                offset += read;
            }
            return bytes;
        } catch (Exception e) {
            return null;
        } finally {
            try {
                is.close();
                is = null;
            } catch (IOException e) {
                return null;
            }
        }
    }

    /**
     * 杀死Agent以及Agent所在容器
     *
     * @param agent 要杀死的Agent
     */
    public static void killContainerOf(Agent agent) {
        AgentContainer containerController = agent.getContainerController();
        agent.doDelete();
        new Thread(() -> {
            try {
                containerController.kill();
            } catch (StaleProxyException e) {
                logger.severe("\nHad exception on killContainerOf\n" + e.getMessage());
                e.printStackTrace();
            }
        }).start();
    }

    /**
     * 初始化一个JADE主容器
     *
     * @param host        容器所在的主机地址
     * @param port        容器所在的主机端口
     * @param containName 容器名称
     * @param namePrefix  Agent名字的前缀。Agent的名字组成：namePrefix_数字，如：Chinese_1,Chinese_2
     * @return
     */
    public static ContainerController initMainAgentContainer(String host, String port, String containName, String namePrefix) {
        Runtime rt = Runtime.instance();
        Profile p = new ProfileImpl();
        p.setParameter(Profile.MAIN_HOST, host);
        p.setParameter(Profile.MAIN_PORT, port);
        p.setParameter(Profile.CONTAINER_NAME, containName);
        p.setParameter(Profile.AGENT_TAG, namePrefix);
        return rt.createMainContainer(p);
    }

    /**
     * 初始化一个JADE外围容器
     *
     * @param host        容器所在的主机地址
     * @param port        容器所在的主机端口
     * @param containName 容器名称
     * @param namePrefix  Agent名字的前缀。Agent的名字组成：namePrefix_数字，如：Chinese_1,Chinese_2
     * @return
     */
    public static ContainerController initAgentContainer(String host, String port, String containName, String namePrefix) {
        Runtime rt = Runtime.instance();
        Profile p = new ProfileImpl();
        p.setParameter(Profile.MAIN_HOST, host);
        p.setParameter(Profile.MAIN_PORT, port);
        p.setParameter(Profile.CONTAINER_NAME, containName);
        p.setParameter(Profile.AGENT_TAG, namePrefix);
        return rt.createAgentContainer(p);
    }

    /**
     * 批量初始化Agent
     *
     * @param container      Agent生存的容器
     * @param agentClassName Agent实例类
     * @param nums           Agent数量
     * @param args           初始化参数数组
     */
    public static void initAgents(ContainerController container, String agentClassName, Object[] args, Integer nums) {
        for (int i = 1; i <= nums; i++) {
            try {
                container.createNewAgent("%A" + i, agentClassName, args);
            } catch (StaleProxyException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 启动Agent
     *
     * @param host      IP
     * @param port      端口
     * @param AgentName Agent名字
     * @return
     */
    public static AgentController startAgent(String host, String port, String AgentName) {
        Runtime rt = Runtime.instance();
        Profile p = new ProfileImpl();
        p.setParameter(Profile.MAIN_HOST, host);
        p.setParameter(Profile.MAIN_PORT, port);
        p.setParameter(Profile.CONTAINER_NAME, "China");
        //p.setParameter(Profile.AGENT_TAG, "china_");
        ContainerController cc = rt.createAgentContainer(p);
        if (null != cc) {
            try {
                Object[] obj = new Object[1];
                obj[0] = new String("");
                AgentController ac = cc.createNewAgent("%A" + AgentName, "cn.newangels.jade.agents.MaintenanceUnit.MaintenanceUnitA", null);
                ac.start();
                return ac;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * true:already in using  false:not using
     *
     * @param port
     */
    public static boolean isLoclePortUsing(int port) {
        boolean flag = true;
        try {
            flag = isPortUsing("127.0.0.1", port);
        } catch (Exception e) {
        }
        return flag;
    }

    /**
     * true:already in using  false:not using
     *
     * @param host
     * @param port
     * @throws UnknownHostException
     */
    public static boolean isPortUsing(String host, int port) throws UnknownHostException {
        boolean flag = false;
        InetAddress theAddress = InetAddress.getByName(host);
        try {
            Socket socket = new Socket(theAddress, port);
            flag = true;
        } catch (IOException e) {

        }
        return flag;
    }

}
